Blueprint Help Send comments on this topic.
Processing Code

Glossary Item Box

Overview

Processing code is called when an event fires in the circuitry that is to be handled by user provided code.  The Process() processing code function is called from the Execute() harness code function to perform the actual processing required.

The intended purpose of the Process() function is to extract the required data references using appropriate access functions and call appropriate topic code to operate on input data and generate output data.

For more information on entering processing code, refer to Entering Processing Code.  For more information about the content of a circuit definition, refer to Circuit Definitions.

Example

In the examples below the 'black' code is auto-generated by the translator, whilst the 'red' code is the additional example code and 'green' to highlight comments.

The following example shows the processing code for an FFT method.  This code is constructing an output record in which to store the output from the processing then getting references to the input and output data and then passing these to the topic code functions that perform the real processing:

Uns Cct1_FFTMthdElem::Process()
{
   Uns failed = FALSE;
     
   // construct output store
   this->Trigger2_OutTst1Cxn().Construct();

   // extract references to input/output stores
   ComplexArray& in  = this->Trigger2_InTst1Rec.Data();   
   ComplexArray& out = this->Trigger2_OutTst1Rec.Data();

   // do processing
   FFT1dc( in, out );
   Filter( out );
      
   return ! failed;
}

WARNING: modifying data through a pointer provided by a read-access connection is dangerous.  You must ensure that the circuitry prevents multiple simultaneous readers.  If in doubt, copy the data to the output store and modify it there.  Some mathematical functions perform 'in-place' calculations writing the results back to the same memory location, to optimize for memory usage.  If no 'out-of-place' function is available, the data can be copied to avoid exclusion issues but this carries a performance penalty.

Dangerous

Uns Cct1_FFTMthdElem::Process()
{
   Uns failed = FALSE;
     
   // construct output store
   this->Trigger2_OutTst1Cxn().Construct();

   // extract references to input/output stores
   ComplexArray& in  = this->Trigger2_InTst1Rec.Data();   
   ComplexArray& out = this->Trigger2_OutTst1Rec.Data();

   // do processing
   Filter( in );      // dangerous in-place 
   FFT1dc( in, out );
      
   return ! failed;
}

Ok

Uns Cct1_FFTMthdElem::Process()
{
   Uns failed = FALSE;
     
   // construct output store
   this->Trigger2_OutTst1Cxn().Construct();

   // extract references to input/output stores
   ComplexArray& in  = this->Trigger2_InTst1Rec.Data();   
   ComplexArray& out = this->Trigger2_OutTst1Rec.Data();

   // do processing
   out = in;            // copy in to out
   Filter( out );     
// in-place now ok
   FFT1dc( out, out );
      
   return ! failed;
}

or

Uns Cct1_FFTMthdElem::Process()
{
   Uns failed = FALSE;
     
   // construct output store
   this->Trigger2_OutTst1Cxn().Construct();

   // extract references to input/output stores
   ComplexArray& in  = this->Trigger2_InTst1Rec.Data();   
   ComplexArray& out = this->Trigger2_OutTst1Rec.Data();

   // do processing
   ComplexArray filtered = in;  // make local copy
   Filter( filtered );           // in-place now ok
   FFT1dc( filtered, out );
      
   return ! failed;
}

Notes

  • When entering code it is useful (but not essential) to use the this prefix for member functions, as this allows the Visual Studio Intellisense to display a list of the available functions and their format. This simplifies the process of accessing the correct CDL function.
  • When writing harness code the coder needs to distinguish between manual and automatic connections as automatic connections are opened and closed by the CLIP infrastructure whereas manual connections are not.  Hence the coder must open/close manual connections explicitly.
  • It is good practice (but by no means always possible) to open/close the manual connections in the Harness code, and simply pass a reference to the data to the Process(). The Process() return value can then be used to decide whether to abort any connections. 
  • When opening a store for write access (whether automatic or manual) the records Construct() call must called, to allocate memory for the data and to assign the memory to the record structure.
  • If a manual connection is aborted, the connection must still be closed.